使用setInterval每秒做多次的細微變化(css改變),當次數夠多畫面就會流暢許多:
let delay = 1000 / 次數
let timer = setInterval(() => {
if(停止條件) clearInterval(timer);
else 改變css
})
let start = Date.now();
let timer = setInterval(function () {
let timePassed = Date.now() - start;
target.style.left = timePassed / 5 + "px";
if (timePassed > 3000) clearInterval(timer); // 3秒後停止,
}, 20);
setTimeout與setInterval來製作動畫時,當更新的頻率過高的時候是有可能導致效能低落的,因為瀏覽器本身有自己的FPS更新效率,如果我們設置的頻率高於瀏覽器的,可能導致耗電還有效能的問題。
requestAnimationFrame用法與setTimeout與setInterval差不多,一樣傳入一個callback,不需傳入秒數,會自動以瀏覽器的更新頻率,requestAnimationFrame(callback)會回傳一個唯一的requestID,可以透過呼叫 cancelAnimationFrame(requestID) 取消此動畫。
let elem = document.getElementById("animate");
let left = 0;
let bound = false;
requestAnimationFrame(Move);
function Move() {
if(left === 0 || left === 350) {
bound = !bound;
}
(bound) ? left++ : left--;
elem.style.left = left + 'px';
window.requestAnimationFrame(Move);
}
基於requestAnimationFrame可以創建一個通用的動畫function:
function animate({timing, draw, duration}) {
let start = performance.now();
requestAnimationFrame(function animate(time) {
// timeFraction 从 0 增加到 1
let timeFraction = (time - start) / duration;
if (timeFraction > 1) timeFraction = 1;
// 计算当前动画状态
let progress = timing(timeFraction);
draw(progress); // 绘制
if (timeFraction < 1) {
requestAnimationFrame(animate);
}
});
}
brick.onclick = function() {
animate({
duration: 2000,
timing: function(timeFraction) {
return timeFraction;
},
draw: function(progress) {
brick.style.left = progress*500 + 'px';
}
});
};
以下例子只需改變timing input即可:
function quad(timeFraction) {
return Math.pow(timeFraction, 2)
}
function circ(timeFraction) {
return 1 - Math.sin(Math.acos(timeFraction));
}